/**
 * ...
 * >author		João Vítor de Souza
 */

package com.cupcakeengine.ui 
{
	
	import com.cupcakeengine.CKEngine;
	import com.cupcakeengine.core.IUpdatable;
	import com.cupcakeengine.display.GameObject;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.Dictionary;

	public class MouseManager extends EventDispatcher implements IUpdatable
	{
		// ___________________________________________________________________ CONSTANTS
		
		// ___________________________________________________________________ CLASS PROPERTIES
		
		private var _vButtonMode				: Vector.<GameObject>;
		private var _vClick						: Vector.<GameObject>;
		private var _vClickListener				: Vector.<Function>;
		private var _vMouseUp					: Vector.<GameObject>;
		private var _vMouseUpListener			: Vector.<Function>;
		private var _vMouseDown					: Vector.<GameObject>;
		private var _vMouseDownListener			: Vector.<Function>;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		
		private static var _instance	: MouseManager;
		private var _stage				: Stage;
		
		// ___________________________________________________________________ GETTERS AND SETTERS
		
		// ___________________________________________________________________ CONSTRUCTOR
		
		public function MouseManager (singleton:SingletonObligate) {}
		
		// ___________________________________________________________________ PUBLIC METHODS
		
		public static function getInstance () : MouseManager
		{
			if (!MouseManager._instance) MouseManager._instance = new MouseManager(new SingletonObligate());
			return MouseManager(MouseManager._instance);
		}
		
		public function init(stage:Stage):void
		{
			_stage = stage;
			
			_vButtonMode = new Vector.<GameObject>;
			_vClick = new Vector.<GameObject>;
			_vClickListener = new Vector.<Function>;
			_vMouseUp = new Vector.<GameObject>;
			_vMouseUpListener = new Vector.<Function>;
			_vMouseDown = new Vector.<GameObject>;
			_vMouseDownListener = new Vector.<Function>;
		}		
		
		public function addButtonMode(object:GameObject):void
		{
			if (_vButtonMode.length == 0) CKEngine.addUpdate(this);
			_vButtonMode.push(object);
		}
		
		public function removeButtonMode(object:GameObject):void
		{
			if (_vButtonMode.indexOf(object) == -1) return;
			
			_vButtonMode.splice(_vButtonMode.indexOf(object), 1);
			
			Mouse.cursor = MouseCursor.ARROW;
			
			if (_vButtonMode.length == 0) CKEngine.removeUpdate(this);			
		}
		
		public function addMouseEvent(object:GameObject, type:String, listener:Function):void
		{
			if (type == MouseEvent.CLICK) {
				if (_vClick.length == 0) _stage.addEventListener(MouseEvent.CLICK, onClick);
				
				_vClick.push(object);
				_vClickListener.push(listener);
			} else if (type == MouseEvent.MOUSE_DOWN) {
				if (_vMouseDown.length == 0) _stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
				
				_vMouseDown.push(object);
				_vMouseDownListener.push(listener);
			} else if (type == MouseEvent.MOUSE_UP) {
				if (_vMouseUp.length == 0) _stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
				
				_vMouseUp.push(object);
				_vMouseUpListener.push(listener);
			}
		}
		
		public function removeMouseEvent(object:GameObject, type:String):void
		{
			if (type == MouseEvent.CLICK) {
				if (_vClick.indexOf(object) == -1) return;			
				
				_vClickListener.splice(_vClick.indexOf(object), 1);
				_vClick.splice(_vClick.indexOf(object), 1);
				
				if (_vClick.length == 0) _stage.removeEventListener(MouseEvent.CLICK, onClick);
			} else if (type == MouseEvent.MOUSE_DOWN) {
				if (_vMouseDown.indexOf(object) == -1) return;			
				
				_vMouseDownListener.splice(_vMouseDown.indexOf(object), 1);
				_vMouseDown.splice(_vMouseDown.indexOf(object), 1);
				
				if (_vMouseDown.length == 0) _stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			} else if (type == MouseEvent.MOUSE_UP) {
				if (_vMouseUp.indexOf(object) == -1) return;			
				
				_vMouseUpListener.splice(_vMouseUp.indexOf(object), 1);
				_vMouseUp.splice(_vMouseUp.indexOf(object), 1);
				
				if (_vMouseUp.length == 0) _stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			}
		}
		
		/* INTERFACE com.mifiz.core.IUpdatable */
		
		public function update():void 
		{
			checkButtonMode(_stage.mouseX, _stage.mouseY);
		}
		
		// ___________________________________________________________________ PRIVATE METHODS
		
		private function checkButtonMode(x:Number, y:Number):void
		{
			var len:int = _vButtonMode.length;
			var object:GameObject;
			for (var i:int = 0; i < len; i++) {
				object = _vButtonMode[i];
				if (x >= object.x  && x <= object.x + object.width) {
					if(y >= object.y && y <= object.y + object.height){
						Mouse.cursor = MouseCursor.BUTTON;
						return;
					}
				}
			}
			
			Mouse.cursor = MouseCursor.ARROW;
		}
		
		private function checkMouse(e:MouseEvent, x:Number, y:Number, vector:Vector.<GameObject>, vectorListener:Vector.<Function>):void
		{
			var len:int = vector.length;
			var object:GameObject;
			var callback:Function;
			for (var i:int = 0; i < len; i++) {
				object = vector[i];
				if (x >= object.x  && x <= object.x + object.width) {
					if (y >= object.y && y <= object.y + object.height) {						
						callback = vectorListener[i];
						if (callback != null) callback(e);
						return;
					}
				}
			}
		}
		
		// ___________________________________________________________________ EVENTS
		
		private function onClick(e:MouseEvent):void 
		{
			checkMouse(e, e.stageX, e.stageY, _vClick, _vClickListener);
		}
		
		private function onMouseUp(e:MouseEvent):void 
		{
			checkMouse(e, e.stageX, e.stageY, _vMouseUp, _vMouseUpListener);
		}		
		
		private function onMouseDown(e:MouseEvent):void 
		{
			checkMouse(e, e.stageX, e.stageY, _vMouseDown, _vMouseDownListener);
		}		
	}
}

class SingletonObligate {}
